#include "pc.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "rs485.h"
#include "string.h"
#include "adcproc.h"
#include "iwdg.h"

#define MAX_DELAY 5000   //最长等待时间，不可超过65535
// 待实现功能：目前如果485接口如果接收出错会一直重新发送并等待接收，死循环了； 应该让接收出错一定次数后直接返回接收出错的命令；

uint8_t CMD_FromPC[CMD_SIZE] = {0};
uint8_t CMD_ToPC[CMD_SIZE] = {0};

uint8_t ADC_Data[1024];
uint16_t RecvTimerCount = 0; // 接收等待时间计数器，单位ms

uint8_t _GenCheckCode(uint8_t *cmd, int start, int end)
{
    uint8_t ans = 0;
    for (int i = start; i <= end; i++)
        ans = (ans + cmd[i]) & 0xff;
    return ans;
}

uint8_t _CheckRecv()
{
    // 校验接收到的数据
    if (CMD_FromPC[0] == 0xE0 && CMD_FromPC[2] != 0)
    {
        if (_GenCheckCode(CMD_FromPC, 1, CMD_FromPC[2] - 1) != CMD_FromPC[CMD_FromPC[2]])
        {
            return 1; // 数据有问题
        }
    }
    return 0; // 数据没问题
}

void _SendCmdToPC()
{
    HAL_UART_Transmit(&huart1, CMD_ToPC, CMD_ToPC[2] + 1, HAL_MAX_DELAY);
    Uart_ResetRx(U1_RxCtrl);
}

void closeAdc()
{
    HAL_TIM_Base_Stop(&htim2);
    HAL_ADC_Stop_IT(&hadc1);
    HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_2);
    AdcEnable = 0;
}

void openAdc()
{
    HAL_TIM_Base_Start(&htim2);
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
    HAL_ADC_Start_IT(&hadc1);
    AdcEnable = 1;
}
// 复位
void Stm32_SoftReset(void)
{
    __set_FAULTMASK(1); // 禁止所有的可屏蔽中断
    NVIC_SystemReset(); // 软件复位
}

void RecvWait(){
    HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
    RecvTimerCount = 0;
    while (U3_RxCtrl.RxOK == 0)
    {
        HAL_IWDG_Refresh(&hiwdg); // 喂狗
        RecvTimerCount++;
        if (RecvTimerCount > MAX_DELAY)
        {
            Stm32_SoftReset();
        }
        HAL_Delay(10);
    }
    
}
void HandShakeWait()
{
    HAL_GPIO_WritePin(Led_GPIO_Port, Led_Pin, GPIO_PIN_SET);
    RecvTimerCount = 0;
    while (U3_RxCtrl.RxOK == 0)
    {
        RecvTimerCount++;
        HAL_IWDG_Refresh(&hiwdg); // 喂狗
        if (RecvTimerCount > 5000)
        {
            CMD_ToPC[1] = 0;
            CMD_ToPC[2] = 5;
            CMD_ToPC[3] = 0xA0;
            CMD_ToPC[4] = 0xFF;
            CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
            _SendCmdToPC();
            break;
        }
        HAL_Delay(1);
    }
    
}

void ProgressCmdFromPC()
{
    if (CMD_FromPC[0] != 0xE0 || CMD_FromPC[2] <= 2 || _CheckRecv() != 0)
    {
        // Uart_ResetRx(U1_RxCtrl);
        return;
    }
    
    CMD_ToPC[0] = 0xE0;

    switch (CMD_FromPC[3])
    {
    // 握手
    case 0xA0:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_HandShake();

            HandShakeWait();

        } while (_485_CheckRecv() != 0);

        if (_485_CMDRecv[2] != 0xA0)
            break;

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();
        break;
    // 获取三轴数据
    case 0x01:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_GetAttitudeAngle();

            RecvWait();

        } while (_485_CheckRecv() != 0);

        if (_485_CMDRecv[2] != 0x01)
            break;

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;
    // 获取磁偏角
    case 0x02:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_GetMagneticAngle();

            RecvWait();

        } while (_485_CheckRecv() != 0);

        if (_485_CMDRecv[2] != 0x02)
            break;

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;
    // 设置磁偏角
    case 0x31:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);
            // E0 00 06 31 SA AB xx
            float angle = ((CMD_FromPC[4] & 0x0f) * 10 + (CMD_FromPC[5] >> 4) + (0.1 * (float)(CMD_FromPC[5] & 0x0f))) * ((CMD_FromPC[4] >> 4) == 0 ? 1 : -1);
            _485_SetMagneticAngle(angle); // 复位接收控制器

            RecvWait();

        } while (_485_CheckRecv() != 0);

        // if(_485_CMDRecv[2]!=0x31) break;
        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;
    // 发送校准命令
    case 0x32:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_CorrectDcm();

            RecvWait();

        } while (_485_CheckRecv() != 0);

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;
    // 发送保存校准命令
    case 0x33:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_SaveCorrectDCMCmd();
            
            RecvWait();

        } while (_485_CheckRecv() != 0);

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;

    case 0x71:
        do
        {
            memset(U3_RxCtrl.RxBuff, 0, U3_RxCtrl.BuffSize); // 清空之前的数据
            Uart_ResetRx(U3_RxCtrl);                         // 复位接收控制器
            _485_GetPlugPressure();

            RecvWait();

        } while (_485_CheckRecv() != 0);

        if (_485_CMDRecv[2] != 0x71)
            break;

        memcpy(CMD_ToPC + 2, _485_CMDRecv + 1, _485_CMDRecv[1]); // 直接把串口3收到的数据发送给上位机
        CMD_ToPC[1] = 0;
        CMD_ToPC[2] = _485_CMDRecv[1] + 1;
        CMD_ToPC[CMD_ToPC[2] + (CMD_ToPC[1] << 8)] = _GenCheckCode(CMD_ToPC, 1, CMD_ToPC[2] + (CMD_ToPC[1] << 8) - 1);
        _SendCmdToPC();

        break;

    default:
        break;
    }

    memset(CMD_FromPC, 0, sizeof(CMD_FromPC));
}